import httpx # Use httpx for async requests
import asyncio # Added for placeholder sleep
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from sqlalchemy import update
from fastapi import HTTPException, status
import logging

from app.core.config import settings
from app.db.models.image import ImageHistory
from app.schemas.image import ImageHistoryCreate
from app.services import credit as credit_service # To deduct credits

logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO) # Basic config for logging

async def call_image_generation_api(prompt: str) -> str:
    """Simulates calling an OpenAI-compatible image generation API."""
    api_key = settings.OPENAI_API_KEY
    model = settings.IMAGE_GEN_MODEL
    # Replace with the actual API endpoint if available
    # api_url = "https://api.openai.com/v1/chat/completions" # Example

    if not api_key:
        logger.error("OPENAI_API_KEY not configured.")
        raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Image generation service not configured.")

    # --- Placeholder Logic --- 
    # In a real scenario, you would make an HTTP request here.
    # For now, we'll return a placeholder URL based on the prompt.
    logger.info(f"Simulating image generation for prompt: '{prompt[:50]}...'")
    await asyncio.sleep(1) # Simulate network delay
    # Simple hash for slightly varied placeholder URLs
    prompt_hash = hash(prompt) % 1000 
    placeholder_url = f"https://picsum.photos/id/{prompt_hash}/512/512" # Using picsum.photos
    # placeholder_url = f"https://via.placeholder.com/512x512.png?text=Generated+for+{prompt[:20].replace(' ', '+')}"
    logger.info(f"Simulation complete. Returning URL: {placeholder_url}")
    return placeholder_url
    # --- End Placeholder --- 

    # --- Example using httpx (replace placeholder with this) ---
    # headers = {
    #     "Authorization": f"Bearer {api_key}",
    #     "Content-Type": "application/json",
    # }
    # data = {
    #     "model": model,
    #     "messages": [{"role": "user", "content": prompt}],
    #     "n": 1, # Request one image
    #     # Add other parameters like size, quality as needed by the specific API
    # }
    # 
    # try:
    #     async with httpx.AsyncClient() as client:
    #         response = await client.post(api_url, headers=headers, json=data, timeout=60.0) # Adjust timeout
    #         response.raise_for_status() # Raise exception for 4xx/5xx errors
    #         
    #         result = response.json()
    #         # Parse the response to get the image URL - this structure depends on the API!
    #         # Example structure (adjust based on actual API response):
    #         if result.get("choices") and len(result["choices"]) > 0:
    #             # Assuming the URL might be nested, e.g., in message content or a dedicated field
    #             image_url = result["choices"][0].get("message", {}).get("content") 
    #             if image_url and isinstance(image_url, str):
    #                 return image_url
    #             else:
    #                  # Look for other potential fields if content isn't the URL
    #                  pass # Add checks for other response structures
    #                  
    #         logger.error(f"Unexpected API response structure: {result}")
    #         raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to parse image generation response.")
    # 
    # except httpx.RequestError as exc:
    #     logger.error(f"HTTP request failed: {exc}")
    #     raise HTTPException(status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail=f"Image generation service request failed: {exc}")
    # except httpx.HTTPStatusError as exc:
    #      logger.error(f"HTTP error response: {exc.response.status_code} - {exc.response.text}")
    #      detail = f"Image generation service failed: {exc.response.status_code}"
    #      if exc.response.is_client_error:
    #          detail += f" - {exc.response.json().get('error', {}).get('message', 'Client Error')}"
    #      raise HTTPException(status_code=exc.response.status_code, detail=detail)
    # except Exception as e:
    #     logger.exception("An unexpected error occurred during image generation API call.")
    #     raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="An unexpected error occurred.")
    # --- End Example --- 

async def add_image_history(db: AsyncSession, history_entry: ImageHistoryCreate) -> ImageHistory:
    """Adds a record to the image generation history."""
    db_history = ImageHistory(**history_entry.model_dump())
    db.add(db_history)
    await db.commit()
    await db.refresh(db_history)
    return db_history

async def generate_image_and_log(
    db: AsyncSession,
    user_id: int,
    prompt: str,
    generation_cost: int = 1 # Default cost
) -> tuple[str, int]:
    """Handles credit deduction, API call, and logging."""
    # 1. Deduct credits (raises HTTPException if insufficient)
    try:
        await credit_service.deduct_credits_for_generation(db, user_id, cost=generation_cost)
        # Note: deduct_credits handles its own commit for the credit change and log.
        logger.info(f"Successfully deducted {generation_cost} credit(s) from user {user_id} for generation.")
    except HTTPException as e:
        logger.warning(f"Credit deduction failed for user {user_id}: {e.detail}")
        # Re-raise credit deduction errors
        raise e
    except Exception as e:
        logger.exception(f"Unexpected error during credit deduction for user {user_id}")
        await db.rollback() # Rollback potential db changes if deduction started but failed unexpectedly
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Credit deduction failed unexpectedly.")

    # 2. Call external API
    image_url = "" # Initialize image_url
    try:
        image_url = await call_image_generation_api(prompt)
        logger.info(f"Image generated successfully for user {user_id}. URL: {image_url}")
    except HTTPException as e:
        # If API call fails, we might want to refund the credits
        # This requires careful consideration of idempotency and potential race conditions.
        # Simplest approach for now: log the failure but don't automatically refund.
        logger.error(f"Image generation API failed for user {user_id} AFTER credit deduction. Manual review may be needed. Error: {e.detail}")
        # Re-raise the API error
        raise e
    except Exception as e:
        logger.exception(f"Unexpected error calling image generation API for user {user_id} after credit deduction.")
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Image generation call failed unexpectedly after credit deduction.")

    # 3. Log generation history (if API call succeeded)
    history_id = -1 # Default to -1 if logging fails
    try:
        history_entry = ImageHistoryCreate(
            user_id=user_id,
            prompt=prompt,
            image_url=image_url # Use the obtained URL
        )
        db_history = await add_image_history(db, history_entry)
        history_id = db_history.id
        logger.info(f"Image generation history logged successfully for user {user_id}. History ID: {history_id}")
        # History log committed within add_image_history
    except Exception as e:
        # If logging fails after successful generation and deduction, it's problematic.
        # Log the error, but the user still got the image and paid.
        logger.exception(f"Failed to log image history for user {user_id} after successful generation.")
        # Don't raise an error to the user here, as they received the image URL.
        # Consider a background task for retrying logging or alerting admins.
        # For now, return the URL but with a placeholder ID or indicate logging failed.
        # history_id remains -1

    return image_url, history_id

async def get_user_image_history(
    db: AsyncSession,
    user_id: int,
    skip: int = 0,
    limit: int = 100
) -> list[ImageHistory]:
    """Retrieves non-deleted image generation history for a user."""
    result = await db.execute(
        select(ImageHistory)
        .filter(ImageHistory.user_id == user_id, ImageHistory.is_deleted == False)
        .order_by(ImageHistory.created_at.desc())
        .offset(skip)
        .limit(limit)
    )
    return list(result.scalars().all())

async def delete_image_history_entry(db: AsyncSession, user_id: int, history_id: int) -> bool:
    """Marks an image history entry as deleted (soft delete)."""
    stmt = (
        update(ImageHistory)
        .where(ImageHistory.id == history_id, ImageHistory.user_id == user_id)
        .values(is_deleted=True)
    )
    result = await db.execute(stmt)
    await db.commit()
    return result.rowcount > 0 # Return True if a row was updated
